/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.ieslaferreria.creditsintesis.controllers;

import com.jme.bounding.BoundingBox;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jmex.terrain.TerrainBlock;
import com.jmex.terrain.TerrainPage;
import edu.ieslaferreria.creditsintesis.logicgame.ActionStates;
import edu.ieslaferreria.creditsintesis.logicgame.MobilObject;
import edu.ieslaferreria.creditsintesis.logicgame.StateMachine;
import edu.ieslaferreria.creditsintesis.logicgame.actions.ActionEvent;
import edu.ieslaferreria.creditsintesis.logicgame.actions.ChangedLocationEvent;
import edu.ieslaferreria.creditsintesis.logicgame.actions.ProcessMobileObjectStateEvent;
import edu.ieslaferreria.creditsintesis.logicgame.actions.ProcessObjectStateEvent;
import edu.ieslaferreria.creditsintesis.logicgame.actions.RmiEvent;
import edu.ieslaferreria.creditsintesis.logicgame.statemachineimpl.PlayerStateMachine;
import edu.ieslaferreria.creditsintesis.rmi.GameEvent;

/**
 * Esta clase es un controlador que sirve para limitar el mapa de External World
 * (Mundo Exterior) por tanto mantendrá los objetos en el suelo, hará
 * que colisionen y todo lo que tiene que ver con la posicione en le mapa.
 * @author Josep
 */
public class ExternalWorldController extends WorldController{

    public ExternalWorldController(TerrainPage terrainPage, ActionStates actionStates){
        super(terrainPage, actionStates);
    }
    public ExternalWorldController(TerrainBlock terrainBlock, ActionStates actionStates){
        super(terrainBlock, actionStates);
    }

    public ExternalWorldController(TerrainPage terrainPage, ActionStates actionStates, CollisionController col){
        super(terrainPage, actionStates, col);
    }
    public ExternalWorldController(TerrainBlock terrainBlock, ActionStates actionStates, CollisionController col){
        super(terrainBlock, actionStates, col);
    }

    public RmiEvent processAction(ProcessMobileObjectStateEvent evt) {
        RmiEvent gm;
        if(this.getAction(evt.getActionId())==null){
            return null;
        }

        Vector3f oldPos = new Vector3f(evt.getObjectWithStates().getLocalTranslation());
        Quaternion oldQuaternion = new Quaternion(evt.getObjectWithStates().getLocalRotation());

        //System.out.println("Old loc: (" + oldPos.getX() + "," + oldPos.getY() + "," + oldPos.getZ() + ")");
        System.out.println("ActionId: " + evt.getActionId() );

        this.getAction(evt.getActionId()).performAction(evt);
        evt.getObjectWithStates().updateGeometricState(evt.getTime(), false);

        //System.out.println("altura max: " + (oldPos.getY()-(((BoundingBox)evt.getObjectWithStates().getWorldBound()).yExtent/1.05)));
        //System.out.println("altura terreny: " + getTerrainPage().getHeight(evt.getObjectWithStates().getLocalTranslation()));

        if(getCollisionController().hasCollision((MobilObject) evt.getObjectWithStates())){
            /*System.out.println("collision loc: ("
                    + evt.getObjectWithStates().getLocalTranslation().getX()
                    + "," + evt.getObjectWithStates().getLocalTranslation().getY()
                    + "," + evt.getObjectWithStates().getLocalTranslation().getZ()
                    + ")");*/

            evt.getObjectWithStates().setLocalTranslation(oldPos);
            evt.getObjectWithStates().setLocalRotation(oldQuaternion);
            evt.getObjectWithStates().updateGeometricState(evt.getTime(), false);


            evt.getObjectWithStates().processTransition(PlayerStateMachine.TR_OBSTACLE);
            gm = new ChangedLocationEvent(oldQuaternion,oldPos,evt.getObjectWithStates().getName());

            //System.out.println("Old loc: (" + oldPos.getX() + "," + oldPos.getY() + "," + oldPos.getZ() + ")");
            /*System.out.println("Collision: ("
                    + getCollisionController().hasCollision((MobilObject) evt.getObjectWithStates())
                    + ")");*/
//        }else if( (oldPos.getY()-(((BoundingBox)evt.getObjectWithStates().getWorldBound()).yExtent/2))
        }else if( FastMath.abs(oldPos.getY()
                -getTerrainPage().getHeight(evt.getObjectWithStates().getLocalTranslation()))
                >evt.getObjectWithStates().getHeight()/0.8){
            evt.getObjectWithStates().setLocalTranslation(oldPos);
            evt.getObjectWithStates().setLocalRotation(oldQuaternion);
            evt.getObjectWithStates().updateGeometricState(evt.getTime(), false);
            evt.getObjectWithStates().processTransition(PlayerStateMachine.TR_OBSTACLE);
            gm = new ChangedLocationEvent(oldQuaternion,oldPos,evt.getObjectWithStates().getName());
            System.out.println("Altura Old loc: (" + oldPos.getX() + "," + oldPos.getY() + "," + oldPos.getZ() + ")");
            System.out.println("Mida objecte: (" + evt.getObjectWithStates().getHeight() + ")");

        }else if(getLimits().x>0
                && (getLimits().x<evt.getObjectWithStates().getLocalTranslation().x
                    || (-getLimits().x)>evt.getObjectWithStates().getLocalTranslation().x)
                || getLimits().y>0
                && (getLimits().y<evt.getObjectWithStates().getLocalTranslation().y
                    || (-getLimits().y)>evt.getObjectWithStates().getLocalTranslation().y)
                || getLimits().z>0
                && (getLimits().z<evt.getObjectWithStates().getLocalTranslation().z
                    || (-getLimits().z)>evt.getObjectWithStates().getLocalTranslation().z)){
            evt.getObjectWithStates().setLocalTranslation(oldPos);
            evt.getObjectWithStates().setLocalRotation(oldQuaternion);
            evt.getObjectWithStates().updateGeometricState(evt.getTime(), false);
            evt.getObjectWithStates().processTransition(PlayerStateMachine.TR_OBSTACLE);
            gm = new ChangedLocationEvent(oldQuaternion,oldPos,evt.getObjectWithStates().getName());
        }else{
            Quaternion newQuaternion = new Quaternion(evt.getObjectWithStates().getLocalRotation());

            evt.getObjectWithStates().processTransition(PlayerStateMachine.TR_FREE_WAY);
            getActionstates().positionObjectWithStatesChanged(evt.getObjectWithStates(),
                                        oldPos,
                                        evt.getObjectWithStates().getLocalTranslation());
            levelingWithTerrain(evt.getObjectWithStates());
            gm = new ChangedLocationEvent(newQuaternion,evt.getObjectWithStates().getLocalTranslation(),
                                          evt.getObjectWithStates().getName());
        }


        return gm;
    }

    public RmiEvent processAction(ProcessObjectStateEvent evt) {
        // por hacer
        RmiEvent gm = new RmiEvent(null);
        if(this.getAction(evt.getActionId())==null){
            return null;
        }
        if(this.getAction(evt.getActionId()).performAction(evt)){
            evt.getObjectWithStates().processTransition(StateMachine.TR_ACTION_TAKEN);
        }else{
            evt.getObjectWithStates().processTransition(StateMachine.TR_ACTION_DENIED);
        }
        return gm;
    }

    public RmiEvent processAction(ActionEvent evt) {

        RmiEvent gm;

        if(evt instanceof ProcessMobileObjectStateEvent){
            gm=processAction((ProcessMobileObjectStateEvent) evt);
        }else if(evt instanceof ProcessObjectStateEvent){
            gm=processAction((ProcessObjectStateEvent) evt);
        }else{
            if(this.getAction(evt.getActionId())==null){
                return null;
            }
            this.getAction(evt.getActionId()).performAction(evt);
                return null;
        }

        return gm;
    }
 }